import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.subplots as sp
import plotly.graph_objects as go
from sklearn.feature_selection import mutual_info_regression
# Defina o símbolo do ativo que você deseja analisar
ativo = "AAPL" # Exemplo: Apple Inc.
# Defina o intervalo de datas desejado
data_inicio = "2023-01-01"
data_fim = "2023-02-01"
# Baixe os dados do Yahoo Finance e renomeie o DataFrame para 'df'
df = yf.download(ativo,
start=data_inicio,
end=data_fim)
[*********************100%%**********************] 1 of 1 completed
# Exiba as primeiras linhas dos dados
display(df.head())
display(df.info())
| Open | High | Low | Close | Adj Close | Volume | |
|---|---|---|---|---|---|---|
| Date | ||||||
| 2023-01-03 | 130.279999 | 130.899994 | 124.169998 | 125.070000 | 124.538666 | 112117500 |
| 2023-01-04 | 126.889999 | 128.660004 | 125.080002 | 126.360001 | 125.823189 | 89113600 |
| 2023-01-05 | 127.129997 | 127.769997 | 124.760002 | 125.019997 | 124.488876 | 80962700 |
| 2023-01-06 | 126.010002 | 130.289993 | 124.889999 | 129.619995 | 129.069321 | 87754700 |
| 2023-01-09 | 130.470001 | 133.410004 | 129.889999 | 130.149994 | 129.597061 | 70790800 |
<class 'pandas.core.frame.DataFrame'> DatetimeIndex: 20 entries, 2023-01-03 to 2023-01-31 Data columns (total 6 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Open 20 non-null float64 1 High 20 non-null float64 2 Low 20 non-null float64 3 Close 20 non-null float64 4 Adj Close 20 non-null float64 5 Volume 20 non-null int64 dtypes: float64(5), int64(1) memory usage: 1.1 KB
None
#1 Tratamento dos dados
#1.1 Verificar o tipo de dados do índice (coluna de datas)
O dataset é identificado pela coluna da data, a fim de realizar análises temporais será necessário que esteja em formato datetime.
# Verificar o tipo de dados do índice (coluna de datas)
print(df.index.dtype)
datetime64[ns]
#1.2 Verificando a existência de dados nulos:
# Verificar valores nulos
valores_nulos = df.isnull().sum()
print(valores_nulos)
Open 0 High 0 Low 0 Close 0 Adj Close 0 Volume 0 dtype: int64
Conclusões:
#1.3 Verificando a existência de dados duplicados:
# Verificar se há linhas duplicadas
linhas_duplicadas = df[df.duplicated()]
print(linhas_duplicadas)
Empty DataFrame Columns: [Open, High, Low, Close, Adj Close, Volume] Index: []
Conclusões:
#1.4 Verificar se não há valores negativos utilizando o método .loc para selecionar as linhas onde os valores são negativos e, em seguida, visualizá-los:
linhas_com_valores_negativos = df[df['Open'] < 0]
print(linhas_com_valores_negativos)
Empty DataFrame Columns: [Open, High, Low, Close, Adj Close, Volume] Index: []
Conclusões:
#1.4 Verificar se não há valores com letras: Você pode usar o método .str.isnumeric() para verificar se os valores nas colunas são numéricos:
colunas_numericas = df.apply(pd.to_numeric, errors='coerce').notna().all()
print(colunas_numericas)
Open True High True Low True Close True Adj Close True Volume True dtype: bool
Conclusões:
#1.5 Verificação de Outliers:
import plotly.subplots as sp
# Definir tamanho personalizado para os gráficos
custom_size = (250, 200) # Defina o tamanho desejado, por exemplo, (largura, altura)
# Criar uma figura com subplots
fig = sp.make_subplots(rows=1,
cols=6,
horizontal_spacing=0.1,
subplot_titles=['Open', 'High', 'Low', 'Close', 'Adj Close', 'Volume'])
# Adicionar os boxplots à figura
fig.add_trace(px.box(df, y='Open').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=1)
fig.add_trace(px.box(df, y='High').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=2)
fig.add_trace(px.box(df, y='Low').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=3)
fig.add_trace(px.box(df, y='Close').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=4)
fig.add_trace(px.box(df, y='Adj Close').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=5)
fig.add_trace(px.box(df, y='Volume').update_layout(width=custom_size[0], height=custom_size[1]).data[0], row=1, col=6)
# Atualizar o layout da figura
fig.update_layout(title="Boxplots das Colunas Numéricas", showlegend=False)
# Exibir a figura
fig.show()
Conclusões:
#2 Análise Exploratória dos Dados:
Serão realizadas visualzações e resumos estatísticos em busca de entender melhor os dados.
#2.1 Estatísticas Descritivas:
# Realize uma análise básica dos dados
display(df.describe())
| Open | High | Low | Close | Adj Close | Volume | |
|---|---|---|---|---|---|---|
| count | 20.000000 | 20.000000 | 20.000000 | 20.000000 | 20.000000 | 2.000000e+01 |
| mean | 135.126000 | 137.271498 | 133.737001 | 135.778999 | 135.202166 | 7.218262e+07 |
| std | 5.921998 | 6.074987 | 6.448833 | 6.635885 | 6.607695 | 1.342587e+07 |
| min | 126.010002 | 127.769997 | 124.169998 | 125.019997 | 124.488876 | 5.410510e+07 |
| 25% | 130.422501 | 132.872501 | 129.447498 | 130.584995 | 130.030220 | 6.398552e+07 |
| 50% | 134.455002 | 136.769997 | 133.950005 | 135.240005 | 134.665459 | 6.956585e+07 |
| 75% | 140.454998 | 143.200005 | 139.182499 | 142.027500 | 141.424126 | 8.040838e+07 |
| max | 144.960007 | 147.229996 | 143.080002 | 145.929993 | 145.310043 | 1.121175e+08 |
Conclusões:
#2.2 Distribuição dos dados:
import plotly.graph_objects as go
# Crie subplots com 2 linhas e 3 colunas
fig = sp.make_subplots(rows=2, cols=3)
# Parâmetros para o contorno das barras
marker_line = dict(
color='black',
width=1
)
# Opacidade das barras
opacity = 0.75
# Adicione os histogramas aos subplots com contornos nas barras
fig.add_trace(go.Histogram(
x=df['Open'],
name='Open',
marker=dict(line=marker_line),
opacity=opacity
), row=1, col=1)
fig.add_trace(go.Histogram(
x=df['High'],
name='High',
marker=dict(line=marker_line),
opacity=opacity
), row=1, col=2)
fig.add_trace(go.Histogram(
x=df['Low'],
name='Low',
marker=dict(line=marker_line),
opacity=opacity
), row=1, col=3)
fig.add_trace(go.Histogram(
x=df['Close'],
name='Close',
marker=dict(line=marker_line),
opacity=opacity
), row=2, col=1)
fig.add_trace(go.Histogram(
x=df['Adj Close'],
name='Adj Close',
marker=dict(line=marker_line),
opacity=opacity
), row=2, col=2)
fig.add_trace(go.Histogram(
x=df['Volume'],
name='Volume',
marker=dict(line=marker_line),
opacity=opacity
), row=2, col=3)
# Atualize os títulos e rótulos dos eixos
fig.update_xaxes(title_text='Open', row=1, col=1)
fig.update_xaxes(title_text='High', row=1, col=2)
fig.update_xaxes(title_text='Low', row=1, col=3)
fig.update_xaxes(title_text='Close', row=2, col=1)
fig.update_xaxes(title_text='Adj Close', row=2, col=2)
fig.update_xaxes(title_text='Volume', row=2, col=3)
fig.update_yaxes(title_text='Frequência')
# Atualize o layout do gráfico
fig.update_layout(title_text="Distribuição das Variáveis")
# Exiba o gráfico
fig.show()
Conclusões:
#2.3 Engenharia de Recursos (Feature Engineering):
# Calcular o retorno diário
df_retorno = df.copy()
df_retorno['Retorno Diário'] = df_retorno['Adj Close'].pct_change()
print("\nRetorno Diário:")
display(df_retorno['Retorno Diário'].head())
# Calcular o retorno acumulado
df_retorno['Retorno Acumulado'] = (1 + df_retorno['Retorno Diário']).cumprod()
print("\nRetorno Acumulado:")
display(df_retorno['Retorno Acumulado'].head())
Retorno Diário:
Date 2023-01-03 NaN 2023-01-04 0.010314 2023-01-05 -0.010605 2023-01-06 0.036794 2023-01-09 0.004089 Name: Retorno Diário, dtype: float64
Retorno Acumulado:
Date 2023-01-03 NaN 2023-01-04 1.010314 2023-01-05 0.999600 2023-01-06 1.036380 2023-01-09 1.040617 Name: Retorno Acumulado, dtype: float64
Conclusões:
#2.4 Gráficos de Linha
import plotly.graph_objects as go
# Criar um gráfico de linha com Plotly
fig = go.Figure()
# Adicionar preços de fechamento
fig.add_trace(go.Scatter(x=df.index, y=df['Close'], mode='lines', name='Preço de Fechamento'))
# Atualizar layout
fig.update_layout(title="Gráfico de Linha Preço de Fechamento",
xaxis_title="Data",
yaxis_title="Preço",
showlegend=True)
# Exibir o gráfico
fig.show()
# Gráfico de Linhas para os Preços de Fechamento Ajustados:
fig = go.Figure()
fig.add_trace(go.Scatter(x=df.index,
y=df['Adj Close'],
mode='lines',
name='Preço de Fechamento Ajustado'))
fig.update_layout(title=f"Preço de Fechamento Ajustado de {ativo}",
xaxis_title='Data',
yaxis_title='Preço')
fig.show()
Conclusões:
#2. Análise de Correlações entre as variáveis:
Serão criados graficos Mapas de Calor que nos dão um valor numérico e uma representação gráfica da intensidade do mesmo e Gráficos de Dispersão.
# Selecionar as colunas desejadas
columns_to_include = ['Open', 'High', 'Low', 'Close', 'Adj Close']
# Criar um novo DataFrame com as colunas desejadas
df_subset = df[columns_to_include]
# Calcular a matriz de correlação
correlation_matrix = df_subset.corr()
# Criar um gráfico de mapa de calor (heatmap)
plt.figure(figsize=(5, 4))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=0.5)
plt.title("Matriz de Correlação")
plt.show()
import plotly.subplots as sp
import plotly.graph_objects as go
# Criar uma figura com subplots
fig = sp.make_subplots(rows=1, cols=5, subplot_titles=['Open vs. High',
'Open vs. Low',
'Open vs. Close',
'High vs. Low',
'High vs. Close'])
# Adicionar scatterplots aos subplots
fig.add_trace(go.Scatter(x=df['Open'], y=df['High'], mode='markers', name='Open vs. High'), row=1, col=1)
fig.add_trace(go.Scatter(x=df['Open'], y=df['Low'], mode='markers', name='Open vs. Low'), row=1, col=2)
fig.add_trace(go.Scatter(x=df['Open'], y=df['Close'], mode='markers', name='Open vs. Close'), row=1, col=3)
fig.add_trace(go.Scatter(x=df['High'], y=df['Low'], mode='markers', name='High vs. Low'), row=1, col=4)
fig.add_trace(go.Scatter(x=df['High'], y=df['Close'], mode='markers', name='High vs. Close'), row=1, col=5)
# Atualizar layout
fig.update_layout(title="Scatterplots das Variáveis",
xaxis_title="X-Axis",
yaxis_title="Y-Axis",
showlegend=True) # Mostrar legenda
# Exibir a figura
fig.show()
Conclusões:
Correlação Linear Positiva....
#2. Extra - Gráfico de Velas (Candlestick) com Plotly:
Será criado um gráfico de Candlestick, que é amplamente utilizado no mercado financeiro. Cada candle(vela) representa toda a movimentação de preço de um dia de pregão e traz as informações do preço de abertura, fechamento, máxima e mínima daquele dia. Uma média móvel aritimética (SMA) de 7 períodos aplicada ao preço de fechamento foi calculada para melhor entendermos qual o preço médio do fechamento e a tendência de preços do ativo nesse período analisado.
# Calcular a média móvel aritmética (SMA)
window = 7 # Janela da média móvel
df['SMA'] = df['Close'].rolling(window=window).mean()
# Criar o gráfico de velas (candlestick) com a média móvel
fig = go.Figure()
# Adicionar o gráfico de velas
fig.add_trace(go.Candlestick(x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'], name='Candlestick'))
# Adicionar a média móvel como um segundo eixo
fig.add_trace(go.Scatter(x=df.index,
y=df['SMA'],
mode='lines',
line=dict(color='blue'),
name=f'SMA-{window}'))
# Atualizar layout
fig.update_layout(title="Gráfico de Velas (Candlestick) com Média Móvel",
xaxis_title="Data",
yaxis_title="Preço",
showlegend=True) # Mostrar legenda
# Criar um segundo eixo y para a média móvel
fig.update_layout(yaxis2=dict(title=f'SMA-{window}', overlaying='y', side='right'))
# Exibir o gráfico
fig.show()
from sklearn.feature_selection import mutual_info_regression
import numpy as np
# Defina as variáveis independentes (preços) e a variável dependente (volume)
prices = df[['Open', 'High', 'Low', 'Close']].values
volume = df['Volume'].values
# Calcule a informação mútua entre os preços e o volume
mi_scores = mutual_info_regression(prices, volume)
mi_scores
array([0.09328007, 0. , 0.05589206, 0.11811123])
Conclusões:
Para a variável 'Open': O valor de informação mútua é aproximadamente 0.0933. Isso indica uma dependência positiva (embora não muito forte) entre a variável 'Open' e o volume de negociação. Significa que há alguma relação entre o preço de abertura e o volume, mas essa relação não é muito forte.
Para a variável 'High': O valor de informação mútua é 0. Isso sugere que não há uma dependência linear entre a variável 'High' e o volume de negociação. A informação mútua 0 indica que essas variáveis não têm uma relação linear significativa.
Para a variável 'Low': O valor de informação mútua é aproximadamente 0.0559. Isso indica uma dependência positiva, mas não muito forte, entre a variável 'Low' e o volume de negociação. Assim como no caso da variável 'Open', há alguma relação entre o preço mínimo e o volume, mas não é muito forte.
Para a variável 'Close': O valor de informação mútua é aproximadamente 0.1181. Isso indica uma dependência positiva entre a variável 'Close' (preço de fechamento) e o volume de negociação. Essa dependência é um pouco mais forte do que a observada nas variáveis 'Open' e 'Low'.
O valor 0. (zero) para a variável 'High' significa que, de acordo com a análise de informação mútua, não há uma relação linear significativa entre o preço mais alto ('High') e o volume de negociação. Pode ser o caso de que essas variáveis não estão linearmente relacionadas ou que a relação é muito fraca para ser detectada pela métrica de informação mútua.